package cn.sc.summer.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import cn.sc.summer.constant.model.Result;
import cn.sc.summer.constant.token.TokenConstant;
import cn.sc.summer.gateway.loadbalance.FeignRule;
import cn.sc.summer.gateway.util.IPUtil;
import cn.sc.summer.token.encrypt.TokenUtil;
import cn.sc.summer.token.enums.RequestTypeEnum;
import cn.sc.summer.token.service.EncryptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * 请求内容存储 处理请求内容 内容放在gatewayContext中
 */
@Slf4j
@Component
public class RequestCoverFilter implements GlobalFilter, Ordered {

    @Resource
    private EncryptService encryptService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        HttpHeaders headers = request.getHeaders();
        String requestType = headers.getFirst(TokenConstant.REQUEST_TYPE);

        Optional<RequestTypeEnum> byType = Optional.ofNullable(RequestTypeEnum.getByType(requestType));
        if (!byType.isPresent()) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
            DataBuffer buffer = response.bufferFactory().wrap(encryptService.encryptData(JSONObject.toJSONString(Result.fail())).getBytes());
            return response.writeWith(Mono.just(buffer));
        }

        String apiKey = headers.getFirst(TokenConstant.API_KEY_REQUEST_HEADER);
        if (StrUtil.isBlank(apiKey)) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
            DataBuffer buffer = response.bufferFactory().wrap(encryptService.encryptData(JSONObject.toJSONString(Result.fail())).getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        String serverName = TokenUtil.getApiEncryptKey(apiKey, byType.get());
        FeignRule.SOURCE_SERVER_NAME = serverName;
        FeignRule.SOURCE_SERVER_IP = IPUtil.getIpAddr(request);
        FeignRule.TARGET_PATH = request.getURI().getPath();

        ServerHttpRequest.Builder mutate = request.mutate();
        mutate.header(TokenConstant.API_KEY_REQUEST_HEADER, TokenUtil.getApiEncryptKey(16, serverName, RequestTypeEnum.OPEN_FEIGN));
        ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(request) {
        };
        ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build();
        return chain.filter(mutateExchange);
    }

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }

}

